## 5.3. System Startup and Initialization

In this section, we're going to talk about exactly what happens when the system boots. Understanding this process and the files involved is important for performing various kinds of system configuration.

### 5.3.1. Kernel Boot Messages

The first step is booting the kernel. As described in the previous section, this can be done from floppy or hard drive. As the kernel loads into memory, it will print messages to the system console, but usually also saves them in the system log files as well. As root, you can always check the file /var/log/messages (which contains kernel messages emitted during runtime as well). The command `dmesg` prints out the last lines of the kernel message ring buffer; directly after booting, naturally, you will get the boot messages, such as (not necessarily the same, and not necessarily in the same order):

>     Console: 16 point font, 480 scans
>     Console: colour VGA+ 80x30, 1 virtual console (max 63)
>     pcibios_init : BIOS32 Service Directory structure at 0x000fb1d0
>     pcibios_init : BIOS32 Service Directory entry at 0xfb5a0
>     pcibios_init : PCI BIOS revision 2.00 entry at 0xfb5d0
>     Probing PCI hardware.
>     Calibrating delay loop.. ok - 36.04 BogoMIPS
>     Memory: 14984k/16384k available (552k kernel code, 384k reserved,\
>     464k data)
>     Swansea University Computer Society NET3.035 for Linux 2.0
>     NET3: Unix domain sockets 0.13 for Linux NET3.035.
>     Swansea University Computer Society TCP/IP for NET3.034
>     IP Protocols: ICMP, UDP, TCP
>     VFS: Diskquotas version dquot_5.6.0 initialized
>     Checking 386/387 coupling... Ok, fpu using exception 16 error\
>     reporting.
>     Checking 'hlt' instruction... Ok.
>     Intel Pentium with F0 0F bug - workaround enabled.
>     alias mapping IDT readonly ...  ... done
>     Linux version 2.0.35 (root@rabbit) (gcc version egcs-2.90.29\
>     980515 (egcs-1.0.3 release)) #3 Fri Nov 13 15:07:45 CET 1998
>     Starting kswapd v 1.4.2.2
>     Serial driver version 4.13 with no serial options enabled
>     tty00 at 0x03f8 (irq = 4) is a 16550A
>     tty01 at 0x02f8 (irq = 3) is a 16550A
>     APM BIOS not found.
>     Real Time Clock Driver v1.09
>     Configuring Adaptec (SCSI-ID 7) at IO:330, IRQ 11, DMA priority 5
>     scsi0 : Adaptec 1542
>     scsi : 1 host.
>       Vendor: IBM       Model: DORS-32160        Rev: WA0A
>       Type:   Direct-Access                      ANSI SCSI revision: 02
>     Detected scsi disk sda at scsi0, channel 0, id 0, lun 0
>       Vendor: SANYO     Model: CRD-254S          Rev: 1.05
>       Type:   CD-ROM                             ANSI SCSI revision: 02
>     Detected scsi CD-ROM sr0 at scsi0, channel 0, id 4, lun 0
>     scsi : detected 1 SCSI cdrom 1 SCSI disk total.
>     SCSI device sda: hdwr sector= 512 bytes. Sectors= 4226725 [2063 MB]\
>     [2.1 GB]
>     Partition check:
>      sda: sda1 sda2 sda3
>     VFS: Mounted root (ext2 filesystem) readonly.
>     Adding Swap: 130748k swap-space (priority -1)
>     lp1 at 0x0378, (polling)
>     3c59x.c:v0.99E 5/12/98 Donald Becker http://cesdis.gsfc.nasa.gov/\
>     linux/drivers/vortex.html
>     eth0: 3Com 3c905B Cyclone 100baseTx at 0x6000, 00:10:4b:45:1d:53,\
>     IRQ 12
>       8K byte-wide RAM 5:3 Rx:Tx split, 10baseT interface.
>       Enabling bus-master transmits and whole-frame receives.
>     ISDN subsystem Rev: 1.44/1.41/1.47/1.28/none loaded
>     HiSax: Driver for Siemens chip set ISDN cards
>     HiSax: Version 2.1
>     HiSax: Revisions 1.15/1.10/1.10/1.30/1.8
>     HiSax: Total 1 card defined
>     HiSax: Card 1 Protocol EDSS1 Id=teles (0)
>     HiSax: Teles IO driver Rev. 1.11
>     HiSax: Teles 16.3 config irq:5 isac:980  cfg:d80
>     HiSax: hscx A:180  hscx B:580
>     Teles3: HSCX version A: V2.1  B: V2.1
>     Teles3: ISAC 2086/2186 V1.1
>     HiSax: DSS1 Rev. 1.16
>     HiSax: 2 channels added
>     HiSax: module installed
>     inserting floppy driver for 2.0.35
>     Floppy drive(s): fd0 is 1.44M
>     FDC 0 is an 8272A

These messages are all printed by the kernel itself, as each device driver is initialized. The exact messages printed depend on what drivers are compiled into your kernel and what hardware you have on your system. Here's a quick rundown on what they mean.

First, the kernel reports which console font it has picked and which console type it has detected; note that this involves only the text mode being used by the kernel, not the capabilities of your video card. (An SVGA video card is reported as `VGA+` as far as the console text mode is concerned.)

Next, the kernel gathers information about the PCI bus and checks for any PCI cards present in the system.

The next message printed is the "BogoMips" calculation for your processor. This is an utterly bogus (hence the name) measurement of processor speed, which is used to obtain optimal performance in delay loops for several device drivers. The kernel also prints information on the system memory:

>     Memory: 14984k/16384k available (552k kernel code, 384k reserved, 464k data)

Here, we see that 14984k of RAM are available for the system to use. This means the kernel itself is using 1400k.

The networking code in the kernel is then initialized and the CPU type checked. You can see from the line:

>     Intel Pentium with F0 0F bug - workaround enabled.

that the Linux kernel is even clever enough to detect the infamous Pentium bug and provide a workaround. The line:

>     Linux version 2.0.35 (root@rabbit) (gcc version egcs-2.90.29 980515\
>     (egcs-1.0.3 release)) #3 Fri Nov 13 15:07:45 CET 1998

tells you the version number of the kernel and who has compiled it on which machine (in this case, it was root on the machine rabbit and which compiler was used). The serial device driver is then initialized, which prints information on each detected serial port. A line such as:

>     tty00 at 0x03f8 (irq = 4) is a 16550A

means that the first serial device (/dev/tty00, or COM1) was detected at address 0x03f8, IRQ 4, using 16550A UART functions. Next comes configuration and checking for a SCSI host adapter. The kernel prints out information about all SCSI devices found. The line:

>     Adding Swap: 130748k swap-space (priority -1)

tells you how much swap space the kernel has found. Among the further tasks performed during a typical boot are finding and configuring a parallel port (`lp1`), detecting and configuring the network card, and finally setting up the ISDN subsystem. The last thing it reports is the detection of the floppy disk driver. Depending on your hardware, other messages will be printed in addition to those given in the example. For example, parallel port and SCSI drivers will be initialized at this point, if you have them.

### 5.3.2. init, inittab, and rc files

Once the device drivers are initialized, the kernel executes the program `init`, which is found in /etc, /bin, or /sbin (it's /sbin/init on most systems). `init` is a general-purpose program that spawns new processes and restarts certain programs when they exit. For example, each virtual console has a `getty` process running on it, started by `init`. When you exit from a login session on one of the virtual consoles, the `getty` process exits, and `init` starts a new one, allowing you to log in again.

`init` is also responsible for running a number of programs and scripts when the system boots. Everything `init` does is controlled by the file /etc/inittab. Each line in this file is of the format:

>     code:runlevels:action:command

code is a unique one- or two-character sequence used to identify this entry in the file. Several of the entries must have a particular code to work correctly; more on this later.

runlevels is the list of "runlevels" in which this entry should be executed. A runlevel is a number or letter that specifies the current system state, as far as `init` is concerned. For example, when the system runlevel is changed to 3, all entries in /etc/inittab containing 3 in the runlevels field will be executed. Runlevels are a useful way to group entries in /etc/inittab together. For example, you might want to say that runlevel 1 executes only the bare minimum of configuration scripts, runlevel 2 executes everything in runlevel 1 plus networking configuration, runlevel 3 executes everything in levels 1 and 2 plus dial-in login access, and so on. Today, the Red Hat distribution is set up so that runlevel 5 automatically starts the X Window System graphical interface. The SuSE distribution does it at runlevel 3, and the Debian distribution does so at runlevel 2--provided you have installed X.

For the most part, you don't need to concern yourself with runlevels. When the system boots, it enters the default runlevel (set in /etc/inittab, as we will soon show). On most systems, this default is runlevel 2 or 3. After we discuss normal booting, we'll show you how to enter another runlevel that you will sometimes need to use--runlevel 1, or single-user mode.

Let's take a look at a sample /etc/inittab file:

>     # Set the default runlevel to three
>     id:3:initdefault:

>     # Execute /etc/rc.d/rc.sysinit when the system boots
>     si:S:sysinit:/etc/rc.d/rc.sysinit

>     # Run /etc/rc.d/rc with the runlevel as an argument
>     l0:0:wait:/etc/rc.d/rc 0
>     l1:1:wait:/etc/rc.d/rc 1
>     l2:2:wait:/etc/rc.d/rc 2
>     l3:3:wait:/etc/rc.d/rc 3
>     l4:4:wait:/etc/rc.d/rc 4
>     l5:5:wait:/etc/rc.d/rc 5
>     l6:6:wait:/etc/rc.d/rc 6

>     # Executed when we press ctrl-alt-delete
>     ca::ctrlaltdel:/sbin/shutdown -t3 -rf now

>     # Start agetty for virtual consoles 1 through 6
>     c1:12345:respawn:/sbin/agetty 38400 tty1
>     c2:12345:respawn:/sbin/agetty 38400 tty2
>     c3:45:respawn:/sbin/agetty 38400 tty3
>     c4:45:respawn:/sbin/agetty 38400 tty4
>     c5:45:respawn:/sbin/agetty 38400 tty5
>     c6:45:respawn:/sbin/agetty 38400 tty6

Fields are separated by colons. The last field is the most recognizable: it is the command that `init` executes for this entry. The first field is an arbitrary identifier (it doesn't matter what it is so long as it's unique in the file) while the second indicates what runlevels cause the command to be invoked. The third field tells `init` how to handle this entry; for example, whether to execute the given command once or to respawn the command whenever it exits.

The exact contents of /etc/inittab depend on your system and the distribution of Linux you have installed.

In our sample file, we see first that the default runlevel is set to 3. The action field for this entry is `initdefault`, which causes the given runlevel to be set to the default. That's the runlevel normally used whenever the system boots. You can override the default with any level you want by running `init` manually (which you might do when debugging your configuration) and passing in the desired runlevel as an argument. For instance, the following command shuts down all current processes and starts runlevel 5 (warn all your users to log off before doing this!):

>     tigger# init 5

LILO can also boot in single-user mode (usually runlevel 1)--see the section "Section 5.2.2.3, "Specifying boot time options"" earlier in this chapter.

The next entry tells `init` to execute the script /etc/rc.d/rc.sysinit when the system boots. (The action field is `sysinit`, which specifies that this entry should be executed when `init` is first started at system boot.) This file is simply a shell script containing commands to handle basic system initialization; for example, swapping is enabled, filesystems are checked and mounted, and the system clock is synchronized with the CMOS clock. You can take a look at this file on your system; we'll be talking more about the commands contained therein in Chapter 6, "Managing Filesystems, Swap, and Devices"; see the sections "Section 6.1, "Managing Filesystems"" and "Section 6.2, "Managing Swap Space"." On other distributions, this file might be elsewhere, for example, on SuSE it is /sbin/init.d/boot.

Next, we see that the system executes the script /etc/rc.d/rc when it enters any of the runlevels 0 through 6, with the appropriate runlevel as an argument. rc is a generic startup script that executes other scripts as appropriate for that runlevel. The action field here is `wait`, which tells `init` to execute the given command, and to wait for it to complete execution before doing anything else.

### 5.3.3. rc files

Linux stores startup commands in files with rc in the name, using an old Unix convention. The commands do all the things necessary to have a fully functioning system, like starting the servers or daemons mentioned in Chapter 4, "Basic Unix Commands and Concepts". Thanks to these commands, the system comes up ready with logging facilities, mail, a web server, or whatever you installed and asked it to run. As explained in the previous section, the files are invoked from /etc/inittab. The commands are standard shell commands, and you can simply read the various rc files to see what they do.

In this section, we describe the structure of the rc files, so you understand where everything starts and can start or stop servers manually in the rare case that they don't do what you want them to do. We'll use Red Hat as our model, but once you get the idea of what to look for, you can find the corresponding files on any Linux distribution.

On Red Hat, the top-level rc script is /etc/rc.d/rc. The path is slightly different in other distributions (/etc/init.d/rc on Debian, for instance) but the contents are similar. In the previous section, you could see how the /etc/inittab invokes the script under a variety of circumstances with different numbers from 0 to 6 as arguments. The numbers correspond to runlevels, and each one causes the rc files to invoke a different set of scripts. So our next step is to find the scripts corresponding to each runlevel.

On Red Hat, scripts for each runlevel are stored in the directory /etc/rc.d/rc N.d where N is the runlevel being started. Thus, for runlevel 3, scripts in /etc/rc.d/rc3.d would be used. Again, slightly different conventions are the rule in other distributions. On Debian, for instance, the directory for each runlevel is /etc/rc N.d/.

Take a look in one of those directories; you will see a number of filenames of the form S nn xxxx or K nn xxxx where nn is a number from 00 to 99, and xxxx is the name of some system service. The scripts whose names begin with K are executed by /etc/rc.d/rc first to kill any existing services, then the scripts whose names begin with S are executed to start new services.

The numbers nn in the names are used to enforce an ordering on the scripts as they are executed: scripts with lower numbers are executed before those with higher numbers. The name xxxx is simply used to help you identify which system service the script corresponds to. This naming convention might seem odd, but it makes it easy to add or remove scripts from these directories and have them automatically executed at the appropriate time by /etc/rc.d/rc. For customizing startup scripts, you'll find it convenient to use a graphical runlevel editor, such as `ksysv`, in the KDE (see "Section 11.3, "The K Desktop Environment"" in Chapter 11, "Customizing Your X Environment").

For example, the script to initialize networking might be called S10network, while the script to stop the system logging daemon might be called K70syslog. If these files are placed in the appropriate /etc/rc.d/rc N.d directories, /etc/rc.d/rc will run them, in numerical order, at system startup or shutdown time. If the default runlevel of your system is 3, look in /etc/rc.d/rc3.d to see which scripts are executed when the system boots normally.

Because the same services are started or stopped at different runlevels, the Red Hat distribution uses symbolic links instead of repeating the same script in multiple places. Thus, each S or K file is a symbolic link that points to a central directory that stores startup or shutdown scripts for all services. On Red Hat, this central directory is /etc/rc.d/init.d, while on SuSE and Debian, it is /etc/init.d. On Debian, the directory contains a script called skeleton that you can adapt to start and stop any new daemons you might write.

Knowing the location of a startup or shutdown script is useful in case you don't want to completely reboot or enter a different runlevel, but need to start or stop a particular service. Look in the init.d directory for a script of the appropriate name and execute it, passing the parameter `start` or `stop`. For example, on SuSE, if you want the Apache web server to be running but your system is in a runlevel that does not include Apache, just enter the following:

>     tigger# /sbin/init.d/apache start

Another important system configuration script is /etc/rc.d/rc.local, which is executed after the other system-initialization scripts are run. (How is this accomplished? Generally, a symbolic link to rc.local is made in each /etc/rc.d/rc N.d directory with the name S99local. Since 99 is the largest numerical order any of the S scripts can have, it is executed last. Voila!) You can edit rc.local to accomplish any peculiar or otherwise out-of-place system commands at boot time, or if you're not sure where else they should be executed. Debian doesn't have an equivalent of rc.local script, but nothing stops you from adding it and invoking it from rc if you're used to having it.

The next entry, labeled `ca`, is executed when the key combination Ctrl-Alt-Del is pressed on the console. This key combination produces an interrupt that usually reboots the system. Under Linux, this interrupt is caught and sent to `init`, which executes the entry with the action field of `ctrlaltdel`. The command shown here, `/sbin/shutdown -t3 -rf now`, will do a "safe" reboot of the system. (See the section "Section 5.5, "Shutting Down the System"" later in this chapter.) This way we protect the system from sudden reboot when Ctrl-Alt-Del is pressed.

Finally, the inittab file includes entries that execute /sbin/agetty for the first six virtual consoles. `agetty` is one of the several `getty` variants available for Linux. These programs permit logins on terminals; without them the terminal would be effectively dead and would not respond when a user walked up and pressed a key or mouse button. The various `getty` commands open a terminal device (such as a virtual console, or a serial line), set various parameters for the terminal driver, and execute /bin/login to initiate a login session on that terminal. Therefore, to allow logins on a given virtual console, you must be running `getty` or `agetty` on it. `agetty` is the version used on a number of Linux systems, but others use `getty`, which has a slightly different syntax. See the manual pages for `getty` and `agetty` on your system.

`agetty` takes two arguments: a baud rate and a device name. The port names for Linux virtual consoles are /dev/tty1, /dev/tty2, and so forth. `agetty` assumes the given device name is relative to /dev. The baud rate for virtual consoles should generally be 38400.

Note that the action field for each `agetty` entry is `respawn`. This means that `init` should restart the command given in the entry when the `agetty` process dies, which is every time a user logs out.

Now you should be familiar with `init`, but the various files and commands in /etc/rc.d, which do all of the work, remain a mystery. We can't delve into these files without more background on other system administration tasks, such as managing filesystems. We'll lead you through these tasks in the next few chapters, and eventually all should be clear.

Copyright © 2001 O'Reilly & Associates. All rights reserved.